
//
// !!!修改文件后调用 npm run buildJs 生成 ui-utils-all.js
//

"use strict";

import jQuery from 'jquery';
import { uiUtils } from "./ui-utils-core";
import { globalUtils } from '../global-utils/global-utils-all';
import { _view } from './ui-utils-view';
import { _event } from './ui-utils-event';

/* SOURCE-CODE-START */

/**
 * @namespace uiUtils-dialog
 */

var DIALOG_HTML = [
  '<div class="modal" tabindex="-1">',
  '<div class="modal-dialog">',
  '<div class="modal-content">',
  '<div class="modal-header">',
  '<h5 class="modal-title">{0}</h5>',
  '<button type="button" class="close" data-dismiss="modal" aria-label="Close">',
  '<span aria-hidden="true">&times;</span>',
  '</button>',
  '</div>',
  '<div class="modal-body">',
  '<p>{1}</p>',
  '</div>',
  '<div class="modal-footer">',
  '<button type="button" class="btn btn-secondary x-btn-cancel" data-dismiss="modal">{2}</button>',
  '<button type="button" class="btn btn-primary x-btn-confirm">{3}</button>',
  '</div>',
  '</div>',
  '</div>',
  '</div>',
].join('\n');

var _dialog = {};
uiUtils.dialog = _dialog;

_dialog.BTN_CONFIRM = '.x-btn-confirm';
_dialog.BTN_CANCEL = '.x-btn-cancel';
var JQUERY_DATA_CONTEXT_DATA = 'uiUtils.dialog.contextData';
var JQUERY_DATA_HTML_BACKUP = 'uiUtils.dialog.htmlBackup';

var CUSTOM_ATTR_INITED_FLAG = 'data-ui-modal-inited';
var CUSTOM_ATTR_SHOW_FLAG = 'data-ui-modal-show';
var CUSTOM_EVENT_ON_SHOW = 'on_show.dialog.uiUtils';
var CUSTOM_EVENT_ON_HIDE = 'on_hide.bs.modal.uiUtils';

/**
 * @memberof uiUtils-dialog
 * @description 显示确认框
 * @param {string} message 
 * @param {function} [confirmFn] 
 * @returns {jQuery}
 */
_dialog.showConfirmBox = function (message, confirmFn) {
  var dialogTitle = '${t `操作提示`}';
  var confirmLabel = '${t `确定`}';
  var cancelLabel = '${t `取消`}';
  var dialogMessage = globalUtils.escapeHtml(message);

  var html = globalUtils.formatString(DIALOG_HTML, [dialogTitle, dialogMessage, cancelLabel, confirmLabel]);
  var jqElement = jQuery(html).prependTo('body');

  // 显示确认框
  jqElement.modal({
    keyboard: false,
    backdrop: 'static'
  });

  // 点击确认按钮的事件
  jqElement.on('click', _dialog.BTN_CONFIRM, function (event) {
    jqElement.modal('hide');

    if (globalUtils.isFunction(confirmFn)) {
      confirmFn();
    }
  });

  // 确认框关闭时移除 DOM 元素
  jqElement.on('hidden.bs.modal', function (event) {
    jqElement.remove();
  });

  return jqElement;
};

/**
 * @memberof uiUtils-dialog
 * @description 初始模态框
 * @param {jQuery} jqElement 
 * @returns {jQuery}
 */
_dialog.initModal = function (jqElement) {
  var initedFlag = jqElement.attr(CUSTOM_ATTR_INITED_FLAG);

  if (!(initedFlag === 'true')) {
    jqElement.on(_event.MODAL_SHOW, function () {
      jqElement.trigger(CUSTOM_EVENT_ON_SHOW);
    });

    jqElement.on(_event.MODAL_HIDE, function () {
      jqElement.trigger(CUSTOM_EVENT_ON_HIDE);
    });

    jqElement.on(_event.MODAL_HIDDEN, function () {
      // 解绑指定的事件
      jqElement.off(CUSTOM_EVENT_ON_SHOW);
      jqElement.off(CUSTOM_EVENT_ON_HIDE);
    });

    // 拷贝对话框的内容
    var htmlBackup = jqElement.html();
    if (globalUtils.isNullOrUndefined(htmlBackup)) {
      htmlBackup = globalUtils.emptyStringIfNullOrUndefined(htmlBackup);
      jqElement.data(JQUERY_DATA_HTML_BACKUP, htmlBackup);
    }

    // 标记对话框已被初始
    jqElement.attr(CUSTOM_ATTR_INITED_FLAG, 'true');
  }
};

/**
 * @memberof uiUtils-dialog
 * @description 销毁模态框
 * @param {jQuery} jqElement 
 * @returns {jQuery}
 */
_dialog.destroyModal = function (jqElement) {
  if (globalUtils.isNullOrUndefined(jqElement)) {
    throw new Error('argument#0 "jqElement" is null/undefined');
  }

  var showFlag = jqElement.attr(CUSTOM_ATTR_SHOW_FLAG);
  var destroyFn = function () {
    // 重置对话框的内容
    var htmlBackup = jqElement.data(JQUERY_DATA_HTML_BACKUP);
    jqElement.html(htmlBackup);

    // 解绑在初始阶段绑定的事件
    jqElement.off(_event.MODAL_SHOW);
    jqElement.off(_event.MODAL_HIDE);
    jqElement.off(_event.MODAL_HIDDEN);
    jqElement.off(CUSTOM_EVENT_ON_SHOW);
    jqElement.off(CUSTOM_EVENT_ON_HIDE);

    // 移除对话框已被初始的标记
    jqElement.removeAttr(CUSTOM_ATTR_INITED_FLAG);
  };

  if (showFlag === 'true') {
    var initedFlag = jqElement.attr(CUSTOM_ATTR_INITED_FLAG);

    if (initedFlag === 'true') {
      jqElement.on(_event.MODAL_HIDDEN, function () {
        destroyFn()
      });
    }

    // 隐藏模态框
    return _dialog.hideModal(jqElement);
  } else {
    destroyFn();

    return jqElement;
  }
};

/**
 * @memberof uiUtils-dialog
 * @description 显示模态框
 * @param {jQuery} jqElement 
 * @param {View} [view]
 * @param {*} [opts] - 方法 $().modal([arg]) 的参数
 * @param {*} [opts.contextData] - 设置上下文数据, 在关闭对话框后会自动清除
 * @param {function} [opts.onModalShow] - 对话框显示时自动调用 onModalShow 方法
 * @param {function} [opts.onModalHide] - 对话框隐藏时自动调用 onModalHide 方法
 * @param {boolean} [opts.lockViewConfirmLeave] - 锁定视图在离开时需要确认, 值默认是 false 不锁定
 * @param {Element} [opts.backdropParent] - 自定义对话框背景的父标签
 * @returns {jQuery}
 */
_dialog.showModal = function (jqElement) {
  if (globalUtils.isNullOrUndefined(jqElement)) {
    throw new Error('argument#0 "jqElement" is null/undefined');
  }

  if (jqElement.length <= 0) {
    throw new Error('argument#0 "jqElement" is empty');
  }

  var view;
  var opts;

  if (arguments.length >= 3) {
    view = arguments[1];
    opts = arguments[2];
  } else if (arguments.length >= 2) {
    opts = arguments[1];
  }

  opts = globalUtils.emptyObjectIfNullOrUndefined(opts);
  var backdropParent = opts.backdropParent;
  var contextData = opts.contextData;
  var lockViewConfirmLeave = (opts.lockViewConfirmLeave === true);
  // 初始对话框
  _dialog.initModal(jqElement);

  // 锁定视图在离开时需要确认
  if (lockViewConfirmLeave) {
    if (globalUtils.isNullOrUndefined(view)) {
      throw new Error('opts.lockViewConfirmLeave true, but argument "view" missing')
    }

    var viewScope = view.getViewScope();
    _view.lockViewConfirmLeave(viewScope);
  }

  // 弹出对话框的默认参数
  var defaultOpts = {
    keyboard: false,
    backdrop: 'static'
  };
  // 创建事件处理函数的参数
  var eventData = {
    jqElement: jqElement,
    view: view,
    opts: opts,
    backdrop: 'static'
  };

  if (!globalUtils.isNullOrUndefined(backdropParent)) {
    defaultOpts.backdrop = false;
    eventData.backdrop = false;

    var jqBackdropParent = (backdropParent instanceof jQuery)
      ? backdropParent : jQuery(backdropParent);
    var jqBackdrop;

    if (jqBackdropParent.children('.modal-backdrop').length > 0) {
      jqBackdrop = jQuery('<div class="modal-backdrop" style="visibility:hidden;"></div>');
    } else {
      jqBackdrop = jQuery('<div class="modal-backdrop show"></div>');
    }

    eventData.jqBackdrop = jqBackdrop;
    eventData.jqBackdropParent = jqBackdropParent;
  }

  var showEventFn = createDialogShowEventFn(eventData);
  var hideEventFn = createDialogHideEventFn(eventData);
  // 绑定事件
  jqElement.on(CUSTOM_EVENT_ON_SHOW, showEventFn);
  jqElement.on(CUSTOM_EVENT_ON_HIDE, hideEventFn);
  // 设置对话框的上下文数据
  _dialog.setContextData(jqElement, contextData);

  var newOpts = globalUtils.mergeObjects(defaultOpts, opts);
  jqElement.modal(newOpts);

  return jqElement;
};

/**
 * @memberof uiUtils-dialog
 * @description 隐藏模态框
 * @param {jQuery} jqElement 
 * @returns {jQuery}
 */
_dialog.hideModal = function (jqElement) {
  if (globalUtils.isNullOrUndefined(jqElement)) {
    throw new Error('argument#0 "jqElement" is null/undefined');
  }

  var showFlag = jqElement.attr(CUSTOM_ATTR_SHOW_FLAG);
  // 隐藏模态框
  if (showFlag === 'true') {
    jqElement.modal('hide');
  }

  return jqElement;
};

/**
 * @memberof uiUtils-dialog
 * @description 返回上下文数据
 * @param {jQuery} jqElement 
 * @returns {*}
 */
_dialog.getContextData = function (jqElement) {
  if (globalUtils.isNullOrUndefined(jqElement)) {
    throw new Error('argument#0 "jqElement" is null/undefined');
  }

  return jqElement.data(JQUERY_DATA_CONTEXT_DATA);;
}

/**
 * @memberof uiUtils-dialog
 * @description 设置上下文数据
 * @param {jQuery} jqElement 
 * @param {*} data
 */
_dialog.setContextData = function (jqElement, data) {
  if (globalUtils.isNullOrUndefined(jqElement)) {
    throw new Error('argument#0 "jqElement" is null/undefined');
  }

  jqElement.data(JQUERY_DATA_CONTEXT_DATA, data);
}

/**
 * @memberof uiUtils-dialog
 * @description 创建对话框显示事件的处理函数
 * @param {*} eventData
 */
function createDialogShowEventFn(eventData) {
  if (globalUtils.isNullOrUndefined(eventData)) {
    throw new Error('argument#0 "eventData" is null/undefined');
  }

  var jqElement = eventData.jqElement;
  var opts = eventData.opts;
  var jqBackdrop = eventData.jqBackdrop;
  var jqBackdropParent = eventData.jqBackdropParent;
  var onModalShow = opts.onModalShow;

  var eventFn = function (event) {
    // 标记对话框显示中
    jqElement.attr(CUSTOM_ATTR_SHOW_FLAG, 'true');

    if (!globalUtils.isNullOrUndefined(jqBackdropParent)) {
      jqBackdrop.prependTo(jqBackdropParent);
      jqBackdropParent.addClass('modal-open');

      if (globalUtils.isFunction(onModalShow)) {
        onModalShow();
      }
    }
  };

  return eventFn;
}

/**
 * @memberof uiUtils-dialog
 * @description 创建对话框隐藏事件的处理函数
 * @param {*} eventData
 */
function createDialogHideEventFn(eventData) {
  if (globalUtils.isNullOrUndefined(eventData)) {
    throw new Error('argument#0 "eventData" is null/undefined');
  }

  var jqElement = eventData.jqElement;
  var view = eventData.view;
  var opts = eventData.opts;
  var backdrop = eventData.backdrop;
  var onModalHide = opts.onModalHide;
  var lockViewConfirmLeave = (opts.lockViewConfirmLeave === true);

  var eventFn = function (event) {
    // 移除对话框显示中的标记
    jqElement.removeAttr(CUSTOM_ATTR_SHOW_FLAG);
    // 重置上下文数据
    _dialog.setContextData(jqElement, null);

    // 解锁视图在离开时不需要确认
    if (lockViewConfirmLeave) {
      var viewScope = view.getViewScope();
      _view.unlockViewAllowLeave(viewScope);
    }

    if (globalUtils.isFunction(onModalHide)) {
      onModalHide();
    }

    if (backdrop === false) {
      var jqBackdrop = eventData.jqBackdrop;
      var jqBackdropParent = eventData.jqBackdropParent;
      // 移除遮罩层
      jqBackdrop.remove();

      if (jqBackdropParent.children('.modal-backdrop').length <= 0) {
        jqBackdropParent.removeClass('modal-open');
      }
    }
  };

  return eventFn;
}

/* SOURCE-CODE-END */

export { uiUtils, _dialog };
